#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>


/*
 * 可靠信号与不可靠信号
 */

#if 0

不可靠信号： 也称为非实时信号，不支持排队，信号可能会丢失, 比如发送多次相同的信号, 进程只能收到一次，信号值取值区间为1~31。
可靠信号： 也称为实时信号，支持排队, 信号不会丢失, 发多少次, 就可以收到多少次. 信号值取值区间为32~64。

/* 实时信号与不可靠信号的区别 */
主要就是实时信号支持排队不会丢失。（实时信号还有一个特点，即到达的顺序是可以保证的）


通过系统调用，发送signal信号：kill()，raise()，sigqueue()，alarm()，setitimer()，abort()


/* 在队列中向指定进程发送一个信号和数据 */
/* 新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用 */
int sigqueue(pid_t pid, int sig, const union sigval value);

    sigqueue的第一个参数是指定接收信号的进程id，
    第二个参数确定即将发送的信号，
    第三个参数是一个联合数据结构union sigval，指定了信号传递的参数，即通常所说的4字节值。

    成功返回0,失败返回-1 

typedef union sigval
{ 
    int sival_int; 
    void *sival_ptr; 
}sigval_t; 
 

sigqueue()比kill()传递了更多的附加信息，但sigqueue()只能向一个进程发送信号，而不能发送信号给一个进程组。

#endif


#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

void handler(int, siginfo_t *, void *);


int main(int argc, char *argv[])
{
    struct sigaction act;
    act.sa_sigaction = handler; //sa_sigaction与sa_handler只能取其一
    //sa_sigaction多用于实时信号，可以保存信息
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO; // 设置标志位后可以接收其他进程
    // 发送的数据，保存在siginfo_t结构体中

    if (sigaction(SIGINT, &act, NULL) < 0)
        ERR_EXIT("sigaction error");

    for (; ;)
        pause();

    return 0;

}

void handler(int sig, siginfo_t *info, void *ctx)
{
    printf("recv a sig=%d data=%d data=%d\n",
           sig, info->si_value.sival_int, info->si_int);

}

#if 0



#endif
